<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS实现Geohash算法</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            width: 100vw;
            height: 100vh;
        }
    </style>
    <script>

        // js生成Geohash
        function CreateGeoHash(longitude, latitude, length) {
            if (!longitude && !latitude) {
                console.error('请传入经纬度')
            }
            // 获取base32编码
            const Base32 = function(str) {
                let num = str
                if(typeof num == "string") {
                    num = Number(str)
                }
                if(num >= 0 && num <=9) {
                    return num.toString()
                } else if(num >= 10 && num <= 16){
                    return String.fromCharCode(98 + str - 10)
                } else if(num >= 17 && num <= 18){
                    return String.fromCharCode(106 + str - 17)
                } else if(num >= 19 && num <= 20){
                    return String.fromCharCode(109 + str - 19)
                } else if(num >= 21 && num <= 31){
                    return String.fromCharCode(112 + str - 21)
                }
            }
            let lngExtent = [-180, 180]
            let latExtent = [-90, 90]
            let accuracy = length || 12 // 精度
            let times = (length * 5) / 2
            let result = []
            let lngList = [] // 经度的二进制结果
            let latList = [] // 纬度的二进制结果
            let lngAverage = 0
            let latAverage = 0
            let lngLeftRange = []
            let lngRightRange = []
            let latLeftRange = []
            let latRightRange = []
            for (let i = 0; i < times; i++) {
                lngAverage = eval(lngExtent.join("+")) / lngExtent.length
                latAverage = eval(latExtent.join("+")) / latExtent.length
                lngLeftRange = [lngExtent[0], lngAverage]
                lngRightRange = [lngAverage, lngExtent[1]]
                latLeftRange = [latExtent[0], latAverage]
                latRightRange = [latAverage, latExtent[1]]
                if (longitude >= lngLeftRange[0] && longitude < lngLeftRange[1]) {
                    lngList.push(0)
                    lngExtent = lngLeftRange
                } else {
                    lngList.push(1)
                    lngExtent = lngRightRange
                }
                if (latitude >= latLeftRange[0] && latitude < latLeftRange[1]) {
                    latList.push(0)
                    latExtent = latLeftRange
                } else {
                    latList.push(1)
                    latExtent = latRightRange
                }
            }
            let lngNum = 0
            let latNum = 0
            // 合并：偶数位放经度，奇数位放纬度
            for (let j = 0; j < times * 2; j++) {
                if (j % 2 == 0) {
                    result.push(lngList[lngNum])
                    lngNum++
                } else {
                    result.push(latList[latNum])
                    latNum++
                }
            }
            // 转为十进制，再转base32编码
            let geohash = ''
            let k = 0
            for (let k = 0; k < result.length; k = k + 5) {
                let arr = result.slice(k, k + 5)
                let sum = parseInt(arr.join(''), 2)
                let base32 = Base32(sum)
                geohash += base32
            }
            return geohash
        }

        function load() {
            const result = CreateGeoHash(120.190856853749, 30.1862355009353, 12)
            console.log(result)
        }

    </script>
</head>

<body onload="load()">

</body>

</html>